{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# \"backtesting crypto with exit signal\"\n",
    "> \"How to fetch and backtest crypto data using fastquant\"\n",
    "\n",
    "- toc: true\n",
    "- branch: master\n",
    "- badges: true\n",
    "- comments: true\n",
    "- author: Mikee Jazmines\n",
    "- categories: [crypto, backtest]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<a href=\"https://colab.research.google.com/github/enzoampil/fastquant/blob/master/examples/2020-05-20-backtest_crypto.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "metadata": {},
   "outputs": [],
   "source": [
    "# uncomment to install in colab\n",
    "# !pip3 install fastquant --update\n",
    "# or pip install git+https://www.github.com/enzoampil/fastquant.git@history"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## fetch data from binance"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### If a timestamp is given, it will return upto that timestamp"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "from fastquant import get_crypto_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 62,
   "metadata": {},
   "outputs": [],
   "source": [
    "crypto = get_crypto_data(\"LUNA/USDT\", \n",
    "                         \"2022-01-23 00:00:00\", \n",
    "                         \"2022-02-23 00:00:00\",\n",
    "                         time_resolution='1h'\n",
    "                        )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 63,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>open</th>\n",
       "      <th>high</th>\n",
       "      <th>low</th>\n",
       "      <th>close</th>\n",
       "      <th>volume</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>dt</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2022-02-22 20:00:00</th>\n",
       "      <td>53.84</td>\n",
       "      <td>54.34</td>\n",
       "      <td>53.38</td>\n",
       "      <td>53.70</td>\n",
       "      <td>197495.77</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2022-02-22 21:00:00</th>\n",
       "      <td>53.69</td>\n",
       "      <td>53.95</td>\n",
       "      <td>53.03</td>\n",
       "      <td>53.04</td>\n",
       "      <td>135259.86</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2022-02-22 22:00:00</th>\n",
       "      <td>53.04</td>\n",
       "      <td>53.51</td>\n",
       "      <td>52.60</td>\n",
       "      <td>53.25</td>\n",
       "      <td>125883.42</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2022-02-22 23:00:00</th>\n",
       "      <td>53.25</td>\n",
       "      <td>54.95</td>\n",
       "      <td>53.16</td>\n",
       "      <td>54.74</td>\n",
       "      <td>258616.24</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2022-02-23 00:00:00</th>\n",
       "      <td>54.74</td>\n",
       "      <td>55.95</td>\n",
       "      <td>54.54</td>\n",
       "      <td>55.41</td>\n",
       "      <td>401518.24</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                      open   high    low  close     volume\n",
       "dt                                                        \n",
       "2022-02-22 20:00:00  53.84  54.34  53.38  53.70  197495.77\n",
       "2022-02-22 21:00:00  53.69  53.95  53.03  53.04  135259.86\n",
       "2022-02-22 22:00:00  53.04  53.51  52.60  53.25  125883.42\n",
       "2022-02-22 23:00:00  53.25  54.95  53.16  54.74  258616.24\n",
       "2022-02-23 00:00:00  54.74  55.95  54.54  55.41  401518.24"
      ]
     },
     "execution_count": 63,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "crypto.tail()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import modules\n",
    "import backtrader as bt\n",
    "\n",
    "# Import from package\n",
    "from fastquant.strategies.base import BaseStrategy\n",
    "\n",
    "\n",
    "class RSIStrategy(BaseStrategy):\n",
    "\n",
    "    params = ((\"rsi_period\", 14), (\"rsi_upper\", 70), (\"rsi_lower\", 30))\n",
    "\n",
    "    def __init__(self):\n",
    "\n",
    "        # Initialize global variables\n",
    "        super().__init__()\n",
    "        # Strategy level variables\n",
    "        self.rsi_period = self.params.rsi_period\n",
    "        self.rsi_upper = self.params.rsi_upper\n",
    "        self.rsi_lower = self.params.rsi_lower\n",
    "\n",
    "        if self.strategy_logging:\n",
    "            print(\"===Strategy level arguments===\")\n",
    "            print(\"rsi_period :\", self.rsi_period)\n",
    "            print(\"rsi_upper :\", self.rsi_upper)\n",
    "            print(\"rsi_lower :\", self.rsi_lower)\n",
    "        self.rsi = bt.indicators.RelativeStrengthIndex(period=self.rsi_period, upperband=self.rsi_upper, lowerband=self.rsi_lower)\n",
    "\n",
    "    def buy_signal(self):\n",
    "        return self.rsi[0] < self.rsi_lower\n",
    "\n",
    "    def sell_signal(self):\n",
    "        return self.rsi[0] > self.rsi_upper\n",
    "\n",
    "    def exit_long_signal(self):\n",
    "        return self.rsi[0] >= 50\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## run backtest using optimum values"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [],
   "source": [
    "from fastquant import backtest"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 66,
   "metadata": {},
   "outputs": [],
   "source": [
    "import matplotlib as pl\n",
    "pl.style.use(\"default\")\n",
    "pl.rcParams[\"figure.figsize\"] = (9,5)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "metadata": {},
   "outputs": [],
   "source": [
    "results, history = backtest(RSIStrategy, \n",
    "                               crypto, \n",
    "                            rsi_period = 20,\n",
    "                            rsi_upper = 70,\n",
    "                            rsi_lower = 30,\n",
    "                               plot=False,\n",
    "                               verbose=False,\n",
    "                               return_history=True\n",
    "                              )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "metadata": {},
   "outputs": [],
   "source": [
    "indicators = history['indicators']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>strat_id</th>\n",
       "      <th>strat_name</th>\n",
       "      <th>dt</th>\n",
       "      <th>type</th>\n",
       "      <th>price</th>\n",
       "      <th>size</th>\n",
       "      <th>value</th>\n",
       "      <th>commission</th>\n",
       "      <th>pnl</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-01-28 12:00:00</td>\n",
       "      <td>buy</td>\n",
       "      <td>49.19</td>\n",
       "      <td>2030</td>\n",
       "      <td>99855.70</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-01-28 13:00:00</td>\n",
       "      <td>buy</td>\n",
       "      <td>48.39</td>\n",
       "      <td>2</td>\n",
       "      <td>96.78</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-01-29 08:00:00</td>\n",
       "      <td>sell</td>\n",
       "      <td>53.06</td>\n",
       "      <td>-2032</td>\n",
       "      <td>99952.48</td>\n",
       "      <td>0.0</td>\n",
       "      <td>7865.44</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-01-30 22:00:00</td>\n",
       "      <td>buy</td>\n",
       "      <td>46.04</td>\n",
       "      <td>2340</td>\n",
       "      <td>107733.60</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-01-31 01:00:00</td>\n",
       "      <td>buy</td>\n",
       "      <td>44.56</td>\n",
       "      <td>2</td>\n",
       "      <td>89.12</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-01-31 14:00:00</td>\n",
       "      <td>sell</td>\n",
       "      <td>47.47</td>\n",
       "      <td>-2342</td>\n",
       "      <td>107822.72</td>\n",
       "      <td>0.0</td>\n",
       "      <td>3352.02</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-02-11 01:00:00</td>\n",
       "      <td>buy</td>\n",
       "      <td>51.83</td>\n",
       "      <td>2143</td>\n",
       "      <td>111071.69</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-02-11 14:00:00</td>\n",
       "      <td>sell</td>\n",
       "      <td>54.57</td>\n",
       "      <td>-2143</td>\n",
       "      <td>111071.69</td>\n",
       "      <td>0.0</td>\n",
       "      <td>5871.82</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-02-11 23:00:00</td>\n",
       "      <td>buy</td>\n",
       "      <td>50.32</td>\n",
       "      <td>2324</td>\n",
       "      <td>116943.68</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-02-12 01:00:00</td>\n",
       "      <td>buy</td>\n",
       "      <td>49.89</td>\n",
       "      <td>2</td>\n",
       "      <td>99.78</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>10</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-02-12 17:00:00</td>\n",
       "      <td>sell</td>\n",
       "      <td>52.77</td>\n",
       "      <td>-2326</td>\n",
       "      <td>117043.46</td>\n",
       "      <td>0.0</td>\n",
       "      <td>5699.56</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>11</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-02-17 21:00:00</td>\n",
       "      <td>buy</td>\n",
       "      <td>51.26</td>\n",
       "      <td>2393</td>\n",
       "      <td>122665.18</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>12</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-02-17 22:00:00</td>\n",
       "      <td>buy</td>\n",
       "      <td>51.30</td>\n",
       "      <td>2</td>\n",
       "      <td>102.60</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>13</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-02-19 05:00:00</td>\n",
       "      <td>sell</td>\n",
       "      <td>51.87</td>\n",
       "      <td>-2395</td>\n",
       "      <td>122767.78</td>\n",
       "      <td>0.0</td>\n",
       "      <td>1460.87</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>14</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-02-20 07:00:00</td>\n",
       "      <td>buy</td>\n",
       "      <td>47.66</td>\n",
       "      <td>2604</td>\n",
       "      <td>124106.64</td>\n",
       "      <td>0.0</td>\n",
       "      <td>0.00</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>15</th>\n",
       "      <td>0</td>\n",
       "      <td>rsi_period20_rsi_upper70_rsi_lower30</td>\n",
       "      <td>2022-02-20 23:00:00</td>\n",
       "      <td>sell</td>\n",
       "      <td>50.21</td>\n",
       "      <td>-2604</td>\n",
       "      <td>124106.64</td>\n",
       "      <td>0.0</td>\n",
       "      <td>6640.20</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "    strat_id                            strat_name                  dt  type  \\\n",
       "0          0  rsi_period20_rsi_upper70_rsi_lower30 2022-01-28 12:00:00   buy   \n",
       "1          0  rsi_period20_rsi_upper70_rsi_lower30 2022-01-28 13:00:00   buy   \n",
       "2          0  rsi_period20_rsi_upper70_rsi_lower30 2022-01-29 08:00:00  sell   \n",
       "3          0  rsi_period20_rsi_upper70_rsi_lower30 2022-01-30 22:00:00   buy   \n",
       "4          0  rsi_period20_rsi_upper70_rsi_lower30 2022-01-31 01:00:00   buy   \n",
       "5          0  rsi_period20_rsi_upper70_rsi_lower30 2022-01-31 14:00:00  sell   \n",
       "6          0  rsi_period20_rsi_upper70_rsi_lower30 2022-02-11 01:00:00   buy   \n",
       "7          0  rsi_period20_rsi_upper70_rsi_lower30 2022-02-11 14:00:00  sell   \n",
       "8          0  rsi_period20_rsi_upper70_rsi_lower30 2022-02-11 23:00:00   buy   \n",
       "9          0  rsi_period20_rsi_upper70_rsi_lower30 2022-02-12 01:00:00   buy   \n",
       "10         0  rsi_period20_rsi_upper70_rsi_lower30 2022-02-12 17:00:00  sell   \n",
       "11         0  rsi_period20_rsi_upper70_rsi_lower30 2022-02-17 21:00:00   buy   \n",
       "12         0  rsi_period20_rsi_upper70_rsi_lower30 2022-02-17 22:00:00   buy   \n",
       "13         0  rsi_period20_rsi_upper70_rsi_lower30 2022-02-19 05:00:00  sell   \n",
       "14         0  rsi_period20_rsi_upper70_rsi_lower30 2022-02-20 07:00:00   buy   \n",
       "15         0  rsi_period20_rsi_upper70_rsi_lower30 2022-02-20 23:00:00  sell   \n",
       "\n",
       "    price  size      value  commission      pnl  \n",
       "0   49.19  2030   99855.70         0.0     0.00  \n",
       "1   48.39     2      96.78         0.0     0.00  \n",
       "2   53.06 -2032   99952.48         0.0  7865.44  \n",
       "3   46.04  2340  107733.60         0.0     0.00  \n",
       "4   44.56     2      89.12         0.0     0.00  \n",
       "5   47.47 -2342  107822.72         0.0  3352.02  \n",
       "6   51.83  2143  111071.69         0.0     0.00  \n",
       "7   54.57 -2143  111071.69         0.0  5871.82  \n",
       "8   50.32  2324  116943.68         0.0     0.00  \n",
       "9   49.89     2      99.78         0.0     0.00  \n",
       "10  52.77 -2326  117043.46         0.0  5699.56  \n",
       "11  51.26  2393  122665.18         0.0     0.00  \n",
       "12  51.30     2     102.60         0.0     0.00  \n",
       "13  51.87 -2395  122767.78         0.0  1460.87  \n",
       "14  47.66  2604  124106.64         0.0     0.00  \n",
       "15  50.21 -2604  124106.64         0.0  6640.20  "
      ]
     },
     "execution_count": 75,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "orders = history['orders']\n",
    "orders"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The final value in `results` can be calculated from the `commission` and `pnl` (profit & loss) of all the closed (bought and sold) transactions in history:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "130889.91000000003"
      ]
     },
     "execution_count": 76,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r = results.squeeze()\n",
    "r.final_value"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "130889.91000000002"
      ]
     },
     "execution_count": 77,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "r.init_cash + orders.pnl.sum() - orders.commission.sum()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 80,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Strategy\n",
      "Profit of asset: 30.889910000000032\n"
     ]
    }
   ],
   "source": [
    "profit = (r.final_value - 100000)/100000*100\n",
    "print(\"Strategy\")\n",
    "print(f\"Profit of asset: {profit}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 81,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Buy and hold\n",
      "Start price of asset: 61.71\n",
      "End price of asset: 55.41\n",
      "Profit of asset: -10.209042294603798\n"
     ]
    }
   ],
   "source": [
    "print(\"Buy and hold\")\n",
    "print(f\"Start price of asset: {crypto.iloc[0, 3]}\")\n",
    "print(f\"End price of asset: {crypto.iloc[-1, 3]}\")\n",
    "print(f\"Profit of asset: {(crypto.iloc[-1, 3] - crypto.iloc[0, 3])/crypto.iloc[0, 3]*100}\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "fastquant2",
   "language": "python",
   "name": "venv"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.7"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
